package com.duowan.realtime.scheduled.batch;

import com.duowan.common.util.DateConvertUtils;
import com.duowan.realtime.scheduled.util.MinuteSlotUtil;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.Date;
import java.util.Map;
import java.util.Set;

/**
 * @author tangsicheng
 * @version 1.0
 * @since 1.0
 */
public class MyJobLauncher {
    private static final Logger logger = LoggerFactory.getLogger(MyJobLauncher.class);
    private JobLauncher jobLauncher;
    private Map<String, Job> jobMap30Second;
    private Map<String, Job> jobMap5Minute;
    private Map<String, Job> jobMap1Minute;
    private Map<String, Job> foreverJob;
    private Map<String, Job> getJobMap5Minute2;

    @Scheduled(cron = "0 */5 * * * ?")
    public void startJobEveryFiveMinute() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        startJobMap(jobMap5Minute);
    }

    /**
     * 每5分钟时间段最后55秒执行任务，例如4:50,9:50，14:50
     *
     * @throws JobParametersInvalidException
     * @throws JobExecutionAlreadyRunningException
     * @throws JobRestartException
     * @throws JobInstanceAlreadyCompleteException
     */
    @Scheduled(cron = "50 4/5 * * * ?")
    public void startJobEveryFiveMinute2() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        startJobMap(getJobMap5Minute2);
    }


    @Scheduled(cron = "*/30 * * * * ?")
    public void startJobEvery30Second() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        startJobMap(jobMap30Second);
    }

    @Scheduled(cron = "0 */1 * * * ?")
    public void startJobEveryMinute() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        startJobMap(jobMap1Minute);
    }


    public void startOnceAtInit() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        startJobMap(foreverJob);
        startJobEveryFiveMinute();
        startJobEveryFiveMinute2();
    }


    public void startJobMap(Map<String, Job> jobMap) throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        if (MapUtils.isNotEmpty(jobMap)) {
            Set<String> jobNames = jobMap.keySet();
            for (String jobName : jobNames) {
                Job job = jobMap.get(jobName);
                logger.info(String.format("job %s start at %s", jobName, getCurrentTime("yyyy-MM-dd HH:mm:ss")));
                jobLauncher.run(job, constructJobParameter());
            }
        }
    }

    private JobParameters constructJobParameter() {
        JobParametersBuilder builder = new JobParametersBuilder();
        Date date = new Date();
        builder.addDate("startTime", date);
        builder.addString("tdate", DateConvertUtils.format(date, "yyyy-MM-dd"));
        builder.addString("htime", MinuteSlotUtil.getSlotTimeStr(60, date, "yyyy-MM-dd HH:mm:ss"));
        builder.addString("mtime", MinuteSlotUtil.getSlotTimeStr(5, date, "yyyy-MM-dd HH:mm:ss"));
        builder.addString("mtime14digit", MinuteSlotUtil.getSlotTimeStr(5, date, "yyyyMMddHHmm"));
        builder.addString("tdate8digit", MinuteSlotUtil.getSlotTimeStr(5, date, "yyyyMMdd"));
        return builder.toJobParameters();
    }


    private String getCurrentTime(String pattern) {
        return DateConvertUtils.format(new Date(), pattern);
    }


    public void setJobLauncher(JobLauncher jobLauncher) {
        this.jobLauncher = jobLauncher;
    }


    public void setJobMap30Second(Map<String, Job> jobMap30Second) {
        this.jobMap30Second = jobMap30Second;
    }

    public void setJobMap5Minute(Map<String, Job> jobMap5Minute) {
        this.jobMap5Minute = jobMap5Minute;
    }

    public void setJobMap1Minute(Map<String, Job> jobMap1Minute) {
        this.jobMap1Minute = jobMap1Minute;
    }

    public void setForeverJob(Map<String, Job> foreverJob) {
        this.foreverJob = foreverJob;
    }

    public void setGetJobMap5Minute2(Map<String, Job> getJobMap5Minute2) {
        this.getJobMap5Minute2 = getJobMap5Minute2;
    }
}
